/*

* ------------------------------------------------------------------------
* ------------------------------------------------------------------------
* |     Smart-Shop开源商城系统/ Java商城-首选电商平台系统 请务必保留此注释头信息
* |     开源地址: https://gitee.com/ningbo-qishan/gruul-mall
* ------------------------------------------------------------------------
* ------------------------------------------------------------------------
* |     可正常分享和学习源码,未经授权 不可商用！
* |     商业版中台购买/开源版商业授权 联系技术客服
* |     官网:  https://www.73app.cn/
* ------------------------------------------------------------------------
* ------------------------------------------------------------------------
* |     Copyright (c) 2016-2999 宁波启山智软科技有限公司
* |     版权所有 ,侵权必究！
* ------------------------------------------------------------------------

*/
package com.medusa.gruul.account.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.medusa.gruul.account.api.constant.AccountQueueNameConstant;
import com.medusa.gruul.account.api.entity.MemberCardInfo;
import com.medusa.gruul.account.api.entity.MemberInfo;
import com.medusa.gruul.account.api.entity.MemberPayRule;
import com.medusa.gruul.account.mapper.MemberCardInfoMapper;
import com.medusa.gruul.account.mapper.MemberInfoMapper;
import com.medusa.gruul.account.mapper.MemberPayRuleMapper;
import com.medusa.gruul.account.model.dto.MemberPayDto;
import com.medusa.gruul.account.model.dto.RechargeDto;
import com.medusa.gruul.account.model.vo.MemberCompletedVo;
import com.medusa.gruul.account.service.IMemberPayRuleService;
import com.medusa.gruul.common.core.auth.client.helper.ISecurity;
import com.medusa.gruul.common.core.constant.CommonConstants;
import com.medusa.gruul.common.core.exception.ServiceException;
import com.medusa.gruul.common.core.util.CurUserUtil;
import com.medusa.gruul.common.core.util.IPUtils;
import com.medusa.gruul.common.core.util.SystemCode;
import com.medusa.gruul.common.data.tenant.TenantContextHolder;
import com.medusa.gruul.common.dto.CurUserDto;
import com.medusa.gruul.payment.api.feign.RemotePaymentService;
import com.medusa.gruul.payment.api.model.pay.PayParam;
import com.medusa.gruul.payment.api.model.dto.PayRequestDto;
import com.medusa.gruul.payment.api.model.dto.PayResultDto;
import com.medusa.gruul.platform.api.feign.RemoteMiniInfoService;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description: 会员信息实现类
 * @Author: zhaokw29701
 * @Date: 2020/6/12 22:31
 **/
@Service
public class MemberPayRuleServiceImpl extends ServiceImpl<MemberPayRuleMapper, MemberPayRule> implements IMemberPayRuleService {

    @Autowired
    private MemberPayRuleMapper memberPayRuleMapper;


    @Autowired
    private MemberInfoMapper memberInfoMapper;

    @Autowired
    private MemberCardInfoMapper memberCardInfoMapper;

    @Autowired
    private RemotePaymentService remotePaymentService;

    @Autowired
    private RemoteMiniInfoService remoteMiniInfoService;

    @Override
    public List<MemberPayRule> getMemberPayRule() {
        String tenantId = TenantContextHolder.getTenantId();
        return memberPayRuleMapper.getMemberPayRule(tenantId);
    }

    @Override
    public void saveMemberPayRule(List<MemberPayRule> memberPayRuleList) {
        String tenantId = TenantContextHolder.getTenantId();
        List<MemberPayRule> memberPayRules = memberPayRuleMapper.getMemberPayRule(tenantId);
        for (MemberPayRule memberPayRule : memberPayRules) {
            memberPayRuleMapper.deleteById(memberPayRule.getId());
        }
        for (MemberPayRule memberPayRule : memberPayRuleList) {
            MemberPayRule memberPayRuleTemp = new MemberPayRule();
            memberPayRuleTemp.setState(memberPayRule.getState())
                    .setPayAmount(memberPayRule.getPayAmount())
                    .setDiscountAmount(memberPayRule.getDiscountAmount());
            memberPayRuleMapper.insert(memberPayRuleTemp);
        }
    }

    @Override
    public PayResultDto memberPay(MemberPayDto memberPayDto) {
        String tenantId = TenantContextHolder.getTenantId();
        //微信支付
        if (memberPayDto.getPaymentType().equals(CommonConstants.NUMBER_ONE)) {
            PayRequestDto payRequestDto = new PayRequestDto();
            /*ShopConfigDto shopConfig = remoteMiniInfoService.getShopConfig(tenantId);
            if (shopConfig == null) {
                throw new ServiceException("商户配置不存在");
            }

            PayInfoVo payInfo = shopConfig.getPayInfo();
            if (payInfo == null) {
                throw new ServiceException("支付配置不存在");
            }*/
            //支付渠道 1-微信支付 2-环迅 3-随行 4-盛付通
            Integer payChannel = 1;
            Integer tradeType = 1;
            if (payChannel.equals(CommonConstants.NUMBER_ONE)) {
                tradeType = CommonConstants.NUMBER_ONE;
            } else if (payChannel.equals(CommonConstants.NUMBER_TWO)) {
                tradeType = 101;
            } else if (payChannel.equals(CommonConstants.NUMBER_THREE)) {
                tradeType = 201;
            } else if (payChannel.equals(CommonConstants.NUMBER_FOUR)) {
                tradeType = 301;
            } else {
                tradeType = CommonConstants.NUMBER_ONE;
            }
            String outTradeNo = generateOrderRandomNo(tenantId, 7);
            CurUserDto curUserDto = CurUserUtil.getHttpCurUser();
            String userId = "";
            String openId = "";
            if (curUserDto != null && curUserDto.getUserId() != null) {
                userId = curUserDto.getUserId();
                openId = curUserDto.getOpenId();
            }
            memberPayDto.setTenantId(tenantId);
            memberPayDto.setUserId(userId);
            List<MemberInfo> memberInfos = memberInfoMapper.getMemberInfoByUserId(tenantId, userId);
            List<MemberCardInfo> memberCardInfoList = memberInfos.stream().map(item -> memberCardInfoMapper.getApiMemberCardInfo(item.getMemberCardInfoId())).collect(Collectors.toList());
            memberCardInfoList = memberCardInfoList.stream().sorted(Comparator.comparing(MemberCardInfo::getRankCode).reversed()).collect(Collectors.toList());
            memberPayDto.setMemberCardInfoId(memberCardInfoList.get(0).getId());
            String routekey = AccountQueueNameConstant.MEMBER_PAY_OK_QUEUE_CHANGE;
            BigDecimal totalFee = memberPayDto.getPayAmount();
            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
            if (requestAttributes == null) {
                throw new ServiceException("数据异常");
            }
            HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
            String teminalIp = IPUtils.getIpAddr(request);
            String feeType = "CNY";
            String timeoutExpress = "15m";
            String body = "会员充值";
            MemberCompletedVo memberCompletedVo = new MemberCompletedVo();
            memberCompletedVo.setUserRank(memberPayDto.getUserId())
                    .setId(memberPayDto.getMemberCardInfoId())
                    .setDAmount(memberPayDto.getDiscountAmount())
                    .setPAmount(memberPayDto.getPayAmount())
                    .setType(4);
            String businessParams = JSON.toJSONString(memberCompletedVo);
            payRequestDto.setTenantId(tenantId);
            payRequestDto.setPayChannel(payChannel);
            payRequestDto.setTradeType(tradeType);
            payRequestDto.setOutTradeNo(outTradeNo);
            payRequestDto.setRouteKey(routekey);
            payRequestDto.setOpenId(openId);
            payRequestDto.setTotalFee(totalFee);
            payRequestDto.setTerminalIp(teminalIp);
            payRequestDto.setFeeType(feeType);
            payRequestDto.setTimeoutExpress(timeoutExpress);
            payRequestDto.setBody(body);
            payRequestDto.setBusinessParams(businessParams);
            PayResultDto payResultDto = remotePaymentService.payRequest(payRequestDto);
            log.debug(JSON.toJSONString(payResultDto));
            return payResultDto;
        } else {
            return new PayResultDto();
        }
    }

    @Override
    public Object memberPayPage(RechargeDto recharge) {
        if (recharge.getRuleId() == null){
            throw new ServiceException(SystemCode.PARAM_BIND_ERROR);
        }
        List<MemberInfo> memberInfos = memberInfoMapper.getMemberInfoByUserId(ISecurity.tenantId().must(), ISecurity.user().must().getShopUserId());
        if (CollUtil.isEmpty(memberInfos)){
            throw new ServiceException("非会员无法使用此规则");
        }
        List<MemberCardInfo> memberCardInfos =
                memberInfos.stream().map(
                        item -> memberCardInfoMapper.getApiMemberCardInfo(item.getMemberCardInfoId())
                ).sorted(
                        Comparator.comparing(MemberCardInfo::getRankCode).reversed()
                ).collect(Collectors.toList());
        if (CollUtil.isEmpty(memberCardInfos)){
            throw new ServiceException("暂无可用会员卡");
        }
        MemberPayRule rule = this.getById(recharge.getRuleId());
        PayParam payParam = new PayParam()
                .setSubject("会员充值")
                .setBody("会员充值")
                .setOrderId( generateOrderRandomNo(ISecurity.tenantId().must(), 7))
                .setPayType(recharge.getPayType())
                .setRouteKey(AccountQueueNameConstant.MEMBER_PAY_OK_QUEUE_CHANGE)
                .setPrice(rule.getPayAmount())
                .setSeconds(15*60L)
                .setAttach(
                        JSON.toJSONString(
                                new MemberCompletedVo()
                                    .setId(memberCardInfos.get(0).getId())
                                    .setUserRank(ISecurity.user().must().getShopUserId())
                                    .setDAmount(rule.getDiscountAmount())
                                    .setPAmount(rule.getPayAmount())
                                    .setType(4)
                        )
                );

        return remotePaymentService.toPayPage(payParam).successData().getData();
    }

    @Override
    public PayResultDto userPay(MemberPayDto memberPayDto) {
        String tenantId = TenantContextHolder.getTenantId();
        //微信支付
        if (memberPayDto.getPaymentType().equals(CommonConstants.NUMBER_ONE)) {
            PayRequestDto payRequestDto = new PayRequestDto();
            /*
            ShopConfigDto shopConfig = remoteMiniInfoService.getShopConfig(tenantId);
            if (shopConfig == null) {
                throw new ServiceException("商户配置不存在");
            }

            PayInfoVo payInfo = shopConfig.getPayInfo();
            if (payInfo == null) {
                throw new ServiceException("支付配置不存在");
            }*/
            //支付渠道 1-微信支付 2-环迅 3-随行 4-盛付通
            Integer payChannel = CommonConstants.NUMBER_ONE;
            Integer tradeType = 1;
            if (payChannel.equals(CommonConstants.NUMBER_ONE)) {
                tradeType = CommonConstants.NUMBER_ONE;
            } else if (payChannel.equals(CommonConstants.NUMBER_TWO)) {
                tradeType = 101;
            } else if (payChannel.equals(CommonConstants.NUMBER_THREE)) {
                tradeType = 201;
            } else if (payChannel.equals(CommonConstants.NUMBER_FOUR)) {
                tradeType = 301;
            } else {
                tradeType = CommonConstants.NUMBER_ONE;
            }
            String outTradeNo = generateOrderRandomNo(tenantId, 7);
            CurUserDto curUserDto = CurUserUtil.getHttpCurUser();
            String userId = "";
            String openId = "";
            if (curUserDto != null && curUserDto.getUserId() != null) {
                userId = curUserDto.getUserId();
                openId = curUserDto.getOpenId();
            }
            memberPayDto.setTenantId(tenantId);
            memberPayDto.setUserId(userId);
            String routekey = AccountQueueNameConstant.MEMBER_PAY_OK_QUEUE_CHANGE;
            BigDecimal totalFee = memberPayDto.getPayAmount();
            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
            if (requestAttributes == null) {
                throw new ServiceException("数据异常");
            }
            HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
            String teminalIp = IPUtils.getIpAddr(request);
            String feeType = "CNY";
            String timeoutExpress = "15m";
            String body = "用户充值";
            MemberCompletedVo memberCompletedVo = new MemberCompletedVo();
            memberCompletedVo.setUserRank(memberPayDto.getUserId())
                    .setId(memberPayDto.getMemberCardInfoId())
                    .setDAmount(memberPayDto.getDiscountAmount())
                    .setPAmount(memberPayDto.getPayAmount())
                    .setType(6);
            String businessParams = JSON.toJSONString(memberCompletedVo);
            payRequestDto.setTenantId(tenantId);
            payRequestDto.setPayChannel(payChannel);
            payRequestDto.setTradeType(tradeType);
            payRequestDto.setOutTradeNo(outTradeNo);
            payRequestDto.setRouteKey(routekey);
            payRequestDto.setOpenId(openId);
            payRequestDto.setTotalFee(totalFee);
            payRequestDto.setTerminalIp(teminalIp);
            payRequestDto.setFeeType(feeType);
            payRequestDto.setTimeoutExpress(timeoutExpress);
            payRequestDto.setBody(body);
            payRequestDto.setBusinessParams(businessParams);
            PayResultDto payResultDto = remotePaymentService.payRequest(payRequestDto);
            log.debug(JSON.toJSONString(payResultDto));
            return payResultDto;
        } else {
            return new PayResultDto();
        }
    }

    @Override
    public Object userPayPage(RechargeDto recharge) {
        PayParam payParam = new PayParam()
                .setPayType(recharge.getPayType())
                .setOrderId(generateOrderRandomNo(ISecurity.tenantId().must(), 7))
                .setRouteKey(AccountQueueNameConstant.MEMBER_PAY_OK_QUEUE_CHANGE)
                .setSubject("余额充值")
                .setBody("余额充值")
                .setPrice(recharge.getPayAmount())
                .setSeconds(15 * 60L)
                .setAttach(
                        JSON.toJSONString(
                                new MemberCompletedVo()
                                        .setId(null)
                                        .setUserRank(ISecurity.user().must().getShopUserId())
                                        .setDAmount(BigDecimal.ZERO)
                                        .setPAmount(recharge.getPayAmount())
                                        .setType(6)
                        )
                );
        return remotePaymentService.toPayPage(payParam).successData().getData();
    }

    /**
     * 生成订单编号，格式：租户id+yyMMdd+7位随机数
     *
     * @param range
     * @return
     */
    @SneakyThrows
    public static String generateOrderRandomNo(String tenantId, int range) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
        String format = sdf.format(new Date());
        return tenantId + format + RandomUtil.randomNumbers(range);
    }
}
